package bombita.persistencia;

import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jdom2.Element;

import bombita.controlador.ControladorPersonaje;
import bombita.modelo.CosaDelMapa;
import bombita.modelo.CosaDelMapaSincronica;
import bombita.modelo.Mapa.Mapa;
import bombita.modelo.Personajes.Personaje;

public class DeserializadorJuego
{
	private Map<String, ControladorPersonaje> jugadores;
	private Map<Point, Map<CosaDelMapa, String>> cosas;
	private Mapa mapa;
	
	public DeserializadorJuego (Element raizJuego) throws Exception
	{
		mapa = this.deserializar(raizJuego);
		cosas = null;
	}
	
	public Mapa getMapa ()
	{
		return mapa;
	}
	
	private Mapa deserializar (Element raizJuego) throws Exception
	{
		this.prepararJugadores(raizJuego.getChild("jugadores"));
		this.prepararCosas(raizJuego.getChild("Mapa"));
		
		int maxX = raizJuego.getChild("Mapa").getAttribute("x").getIntValue();
		int maxY = raizJuego.getChild("Mapa").getAttribute("y").getIntValue();
		Mapa mapa = new Mapa(maxX, maxY);
		
		for (Point posicion : cosas.keySet()) {
			Map<CosaDelMapa, String> cosasEnPosicion = cosas.get(posicion);
			for (CosaDelMapa cosa : cosasEnPosicion.keySet()) {
				String idJugador = cosasEnPosicion.get(cosa);
				if (idJugador != null && cosa instanceof Personaje) {
					jugadores.get(idJugador).agregarControlado((Personaje) cosa);
				}
				if (cosa instanceof CosaDelMapaSincronica) {
					mapa.reconocerSincronico((CosaDelMapaSincronica) cosa, posicion);
				} else {
					mapa.reconocer(cosa, posicion);
				}
			}
		}
		return mapa;
	}

	private void prepararJugadores (Element raizJugador) throws Exception
	{
		jugadores = new HashMap<String, ControladorPersonaje>();
		for (Element nodoJugador : raizJugador.getChildren()) {
			String idJugador = nodoJugador.getAttributeValue("id");
			Object jugador = Deserializador.deserializar("bombita.controlador", nodoJugador);
			jugadores.put(idJugador, (ControladorPersonaje) jugador);
		}
	}
	
	private void prepararCosas (Element raizMapa) throws Exception
	{
		cosas = new HashMap<Point, Map<CosaDelMapa, String>>();
		for (Element nodoPosicion : raizMapa.getChildren("posicion")) {
			Map<CosaDelMapa, String> cosasEnPosicion = new HashMap<CosaDelMapa, String>(); 
			for (Element nodoCosa : nodoPosicion.getChildren()) {
				CosaDelMapa cosa = (CosaDelMapa) Deserializador.deserializar("bombita.modelo", nodoCosa);
				String idJugador = nodoCosa.getAttributeValue("jugador");
				cosasEnPosicion.put(cosa, idJugador);
			}
			int x = nodoPosicion.getAttribute("x").getIntValue();
			int y = nodoPosicion.getAttribute("y").getIntValue();
			Point posicion = new Point(x, y);
			cosas.put(posicion, cosasEnPosicion);
		}
	}

	public List<ControladorPersonaje> getJugadores()
	{
		return new ArrayList<ControladorPersonaje>(jugadores.values());
	}
}
